﻿#include "ais_info_model.h"
#include "target/main_ais.hpp"
#include "target/targetbase.hpp"
#include "../../Target/ais/ais_struct.h"
#include "../../common/functions.h"

//kts(节)---> m/s(米/秒)
#define KTS2MS(n)   ((double)((n)*0.5144444)) 

//AIS的通用常量
std::string ais_status[] = {
    ("发动机使用中"), //0
    ("锚泊"),   //1
    ("未操纵"), //2
    ("有限适航性"), //3
    ("受船舶吃水限制"),//4
    ("系泊"),//5
    ("搁浅"), //6
    ("从事捕捞"), //7
    ("航行中"),//8
    ("高速船舶"),//9
    ("WIG"), //10
    ("保留11"), //11
    ("保留 12"), //12
    ("保留 13"), //13
    ("保留 14"), //14
    ("未定义"), //15
    ("Virtual"), //16
    ("Virtual (On Position)"),
    ("Virtual (Off Position)"),
    ("Real"),
    ("Real (On Position)"),
    ("Real(Off Position)") //21
};

std::string ais_type[] = {
    ("捕鱼船"),             //30        0
    ("拖船"),              //31        1
    ("大型拖船"),        //32        2
    ("Vessel Dredging"),            //33        3
    ("从事潜水作业"),              //34        4
    ("从事军事行动"),            //35        5
    ("帆船"),             //36        6     // pjotrc 2010.02.07
    ("游艇"),             //37        7     // pjotrc 2010.02.10
    ("高速船舶"),           //4x        8
    ("领航船"),               //50        9
    ("打捞船"),   //51        10
    ("拖轮"),                        //52        11
    ("港口补给船"),                //53        12
    ("安装有防污染设施或设备的船舶"),   //54        13
    ("执法船舶"),     //55        14
    ("医疗船"),          //58        15
    ("客船"),             //6x        16
    ("货船"),                 //7x        17
    ("油气罐船"),                     //8x        18
    ("未知"),                    //          19

    ("Unspecified"), 		   //type 0	20  // pjotrc 2010.02.01
    ("Reference Point"),		   //01        21
    ("RACON"),     	               //02        22
    ("Fixed Structure"),            //03        23
    ("Spare"),                      //04        24
    ("Light"),                      //05        25
    ("Light w/Sectors"),            //06        26
    ("Leading Light Front"),        //07        27
    ("Leading Light Rear"),         //08        28
    ("Cardinal N Beacon"),          //09        29
    ("Cardinal E Beacon"),          //10        30
    ("Cardinal S Beacon"),          //11        31
    ("Cardinal W Beacon"),          //12        32
    ("Beacon, Port Hand"),          //13        33
    ("Beacon, Starboard Hand"),     //14        34
    ("Beacon, Preferred Channel Port Hand"),         //15        35
    ("Beacon, Preferred Channel Starboard Hand"),    //16        36
    ("Beacon, Isolated Danger"),    //17        37
    ("Beacon, Safe Water"),         //18        38
    ("Beacon, Special Mark"),       //19        39
    ("Cardinal Mark N"),            //20        40
    ("Cardinal Mark E"),            //21        41
    ("Cardinal Mark S"),            //22        42
    ("Cardinal Mark W"),            //23        43
    ("Port Hand Mark"),             //24        44
    ("Starboard Hand Mark"),        //25        45
    ("Preferred Channel Port Hand"),      //26        46
    ("Preferred Channel Starboard Hand"), //27        47
    ("Isolated Danger"),            //28        48
    ("Safe Water"),                 //29        49
    ("Special Mark"),               //30        50
    ("Light Vessel/Rig")            //31        51
};

std::string short_ais_type[] = {
    ("F/V"),                  //30        0
    ("Tow"),                  //31        1
    ("Long Tow"),             //32        2
    ("Dredge"),               //33        3
    ("D/V"),                  //34        4
    ("Mil/V"),                //35        5
    ("S/V"),                  //36        6
    ("Yat"),                  //37        7    // pjotrc 2010.02.10
    ("HSC"),                  //4x        8
    ("P/V"),                  //50        9
    ("SAR/V"),                //51        10
    ("Tug"),                  //52        11
    ("Tender"),               //53        12
    ("PC/V"),                 //54        13
    ("LE/V"),                 //55        14
    ("Med/V"),                //58        15
    ("Pass/V"),               //6x        16
    ("M/V"),                  //7x        17
    ("M/T"),                  //8x        18
    ("?"),                    //          19

    ("AtoN"),                 //00        20   // pjotrc 2010.02.01
    ("Ref. Pt"),		   //01        21
    ("RACON"),     	         //02        22
    ("Fix.Struct."),          //03        23
    ("?"),                    //04        24
    ("Lt"),                   //05        25
    ("Lt sect."),             //06        26
    ("Ldg Lt Front"),         //07        27
    ("Ldg Lt Rear"),          //08        28
    ("Card. N"),              //09        29
    ("Card. E"),              //10        30
    ("Card. S"),              //11        31
    ("Card. W"),              //12        32
    ("Port"),                 //13        33
    ("Stbd"),                 //14        34
    ("Pref. Chnl"),           //15        35
    ("Pref. Chnl"),           //16        36
    ("Isol. Dngr"),           //17        37
    ("Safe Water"),           //18        38
    ("Special"),              //19        39
    ("Card. N"),              //20        40
    ("Card. E"),              //21        41
    ("Card. S"),              //22        42
    ("Card. W"),              //23        43
    ("Port Hand"),            //24        44
    ("Stbd Hand"),            //25        45
    ("Pref. Chnl"),           //26        46
    ("Pref. Chnl"),           //27        47
    ("Isol. Dngr"),           //28        48
    ("Safe Water"),           //29        49
    ("Special"),              //30        50
    ("LtV/Rig")               //31        51
};

std::string ais_info_model::get_nav_status_string(int status) 
{
    if(status > 15)
        return std::string("未知");
    else
        return ais_status[status] ; 
}

std::string ais_info_model::get_vessel_type_string(int ShipType ,int Class ,  bool b_short)
{
    int i=19;                            // pjotrc 2010.02.10 renumber
    if (Class == AIS_ATON)               // pjotrc 2010.02.01
    {
        i = ShipType + 20 ;
    }
    else
        switch(ShipType)
    {
        case 30:
            i=0; break;
        case 31:
            i=1; break;
        case 32:
            i=2; break;
        case 33:
            i=3; break;
        case 34:
            i=4; break;
        case 35:
            i=5; break;
        case 36:
            i=6; break;
        case 37:
            i=7; break;
        case 50:
            i=9; break;
        case 51:
            i=10; break;
        case 52:
            i=11; break;
        case 53:
            i=12; break;
        case 54:
            i=13; break;
        case 55:
            i=14; break;
        case 58:
            i=15; break;
        default:
            i=19; break;
    }

    if ((Class == AIS_CLASS_B) || (Class == AIS_CLASS_A) )    // pjotrc 2010.02.07
    {
        if((ShipType >= 40) && (ShipType < 50))
            i=8;

        if((ShipType >= 60) && (ShipType < 70))
            i=16;

        if((ShipType >= 70) && (ShipType < 80))
            i=17;

        if((ShipType >= 80) && (ShipType < 90))
            i=18;
    }

    if(!b_short)
        return ais_type[i];
    else
        return short_ais_type[i];
}

std::string ais_info_model::get_class_string(int Class , bool b_short)
{
    switch (Class)
    {
    case AIS_CLASS_A:
        return ("A类");
    case AIS_CLASS_B:
        return ("B类");
    case AIS_ATON:
        return b_short ? ("AtoN") : ("助航设备");
    case AIS_BASE:
        return b_short ? ("基站") : ("基站");
    default:
        return b_short ? ("未知") : ("未知");
    }
}
//END AIS的通用常量

ais_info_model::ais_info_model(QObject * parent)
:QStandardItemModel(parent)
{
    init();

    qRegisterMetaType<ship_info>("ship_info");
    connect(this, SIGNAL(update_ais_info_sig(const ship_info&)), this, SLOT(update_ais_info_slot(const ship_info&)), Qt::QueuedConnection);
}

QVariant ais_info_model::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(Qt::Vertical == orientation  && role == Qt::SizeHintRole)
    {
        return QSize(35, 1);
    }

    return QStandardItemModel::headerData(section , orientation , role ) ;
}

QVariant ais_info_model::data(const QModelIndex &index, int role) const
{
    return QStandardItemModel::data(index , role  ) ;
}

void ais_info_model::init()
{
    setColumnCount(AIS_TOTAL_INDEX);
    setHeaderData(AIS_MMSI_INDEX, Qt::Horizontal, QStringLiteral("批号"));
    setHeaderData(AIS_TIME_INDEX, Qt::Horizontal, QStringLiteral("时间"));
    setHeaderData(AIS_LON_INDEX, Qt::Horizontal, QStringLiteral("经度"));
    setHeaderData(AIS_LAT_INDEX, Qt::Horizontal, QStringLiteral("纬度"));
    setHeaderData(AIS_R_INDEX, Qt::Horizontal, QStringLiteral("距离"));
    setHeaderData(AIS_A_INDEX, Qt::Horizontal, QStringLiteral("方位"));
    setHeaderData(AIS_ETATIME_INDEX, Qt::Horizontal, QStringLiteral("到达时间"));
    setHeaderData(AIS_SHIPCLASS_INDEX, Qt::Horizontal, QStringLiteral("AIS类型"));
    setHeaderData(AIS_IMO_INDEX, Qt::Horizontal, QStringLiteral("代码"));
    setHeaderData(AIS_CALLSIGN_INDEX, Qt::Horizontal, QStringLiteral("呼号"));
    setHeaderData(AIS_SHIPNAME_INDEX, Qt::Horizontal, QStringLiteral("名称"));
    setHeaderData(AIS_SHIPTYPE_INDEX, Qt::Horizontal, QStringLiteral("船舶类型"));
    setHeaderData(AIS_NAVSTATUS_INDEX, Qt::Horizontal, QStringLiteral("航行状态"));
    setHeaderData(AIS_SOG_INDEX, Qt::Horizontal, QStringLiteral("对地航速(m/s)"));
    setHeaderData(AIS_COG_INDEX, Qt::Horizontal, QStringLiteral("对地航向"));
    setHeaderData(AIS_HDG_INDEX, Qt::Horizontal, QStringLiteral("真航向"));
    setHeaderData(AIS_ABCD_INDEX, Qt::Horizontal, QStringLiteral("参考点"));
    setHeaderData(AIS_DRAFT_INDEX, Qt::Horizontal, QStringLiteral("吃水深度"));
    setHeaderData(AIS_DESTINATION_INDEX, Qt::Horizontal, QStringLiteral("目的地"));
    setHeaderData(AIS_SHIP_LENGTH_INDEX, Qt::Horizontal, QStringLiteral("船长"));
    setHeaderData(AIS_SHIP_WIDTH_INDEX, Qt::Horizontal, QStringLiteral("船宽"));
}

int ais_info_model::find_item_row(int mmsi)
{
    QList<QStandardItem*> items;
    QString name = QString::number(mmsi);
    items = findItems(name, Qt::MatchFixedString, AIS_MMSI_INDEX);

    if (items.empty())
    {
        return -1;
    }
    else
    {
        return items[0]->row();
    }
}

void ais_info_model::insert_new_row(int row)
{
    QStandardItem * item = new QStandardItem;
    insertRow(row, item);
}

bool ais_info_model::update_ais_info(const ship_info& info)
{
    emit update_ais_info_sig(info);

    return true;
}

void ais_info_model::update_ais_info_slot(const ship_info& info)
{
    int row = find_item_row(info.MMSI);

    //没有找到 添加新行
    if (row < 0)
    {
        row = rowCount();
        insert_new_row(row);
    }

    //更新数据
    setData(index(row, AIS_MMSI_INDEX), QString::number(info.MMSI) , Qt::DisplayRole);
    setData(index(row, AIS_MMSI_INDEX), QString::number(info.MMSI) , Qt::UserRole);
    setData(index(row, AIS_TIME_INDEX), QString::fromLocal8Bit(info.time2String(info.timestamp).c_str()), Qt::DisplayRole);
    setData(index(row, AIS_LON_INDEX), QString::number(info.longitude, 'f', 6), Qt::DisplayRole);
    setData(index(row, AIS_LAT_INDEX), QString::number(info.latitude, 'f', 6), Qt::DisplayRole);

    if (info.r >= 0)
    {
        setData(index(row, AIS_R_INDEX), QString::number(info.r, 'f', 3), Qt::DisplayRole);
        setData(index(row, AIS_A_INDEX), QString::number(info.a, 'f', 3), Qt::DisplayRole);
    }

    setData(index(row, AIS_ETATIME_INDEX), QString("%1 %2 %3 %4").arg(info.ETA_Mo).arg(info.ETA_Day).arg(info.ETA_Hr).arg(info.ETA_Min), Qt::DisplayRole);
    setData(index(row, AIS_SHIPCLASS_INDEX), QString::fromLocal8Bit(get_class_string(info.ship_class).c_str()), Qt::DisplayRole);
    setData(index(row, AIS_IMO_INDEX), QString::number(info.IMO), Qt::DisplayRole);
    setData(index(row, AIS_CALLSIGN_INDEX), QString::fromLocal8Bit(info.callsign.c_str()), Qt::DisplayRole);
    setData(index(row, AIS_SHIPNAME_INDEX), QString::fromLocal8Bit(get_ship_name(info).c_str()), Qt::DisplayRole);
    setData(index(row, AIS_SHIPTYPE_INDEX), QString::fromLocal8Bit(get_vessel_type_string(info.ship_type, info.ship_class).c_str()), Qt::DisplayRole);
    setData(index(row, AIS_NAVSTATUS_INDEX), QString::fromLocal8Bit(get_nav_status_string(info.nav_status).c_str()), Qt::DisplayRole);

    if (!CommonFunction::dfIsEqual(info.sog, SOG_UNVALID))
    {
        //setData(index(row, AIS_SOG_INDEX), QString::number(info.sog, 'f', 3), Qt::DisplayRole);//节
        setData(index(row, AIS_SOG_INDEX), QString::number(KTS2MS(info.sog), 'f', 3), Qt::DisplayRole);//m/s
    }

    if (!CommonFunction::dfIsEqual(info.cog, COG_UNVALID))
    {
        setData(index(row, AIS_COG_INDEX), QString::number(info.cog, 'f', 3), Qt::DisplayRole);
    }

    if (!CommonFunction::dfIsEqual(info.hdg, HDG_UNVALID))
    {
        setData(index(row, AIS_HDG_INDEX), QString::number(info.hdg, 'f', 3), Qt::DisplayRole);
    }

    if ((info.dim_a + info.dim_b + info.dim_c + info.dim_d) == 0)
    {
        setData(index(row, AIS_ABCD_INDEX), "", Qt::DisplayRole);
    }
    else
    {
        setData(index(row, AIS_ABCD_INDEX), QString("%1 %2 %3 %4").arg(info.dim_a).arg(info.dim_b).arg(info.dim_c).arg(info.dim_d), Qt::DisplayRole);
    }

    setData(index(row, AIS_DRAFT_INDEX), QString::number(info.draft, 'f', 3), Qt::DisplayRole);
    setData(index(row, AIS_DESTINATION_INDEX), QString::fromLocal8Bit(info.destination.c_str()), Qt::DisplayRole);

    if ((info.dim_a + info.dim_b) != 0)
    {
        setData(index(row, AIS_SHIP_LENGTH_INDEX), QString::number(info.dim_a + info.dim_b), Qt::DisplayRole);
    }
    else
    {
        setData(index(row, AIS_SHIP_LENGTH_INDEX), "", Qt::DisplayRole);
    }

    if ((info.dim_c + info.dim_d) != 0)
    {
        setData(index(row, AIS_SHIP_WIDTH_INDEX), QString::number(info.dim_c + info.dim_d), Qt::DisplayRole);
    }
    else
    {
        setData(index(row, AIS_SHIP_WIDTH_INDEX), "", Qt::DisplayRole);
    }
}

std::string ais_info_model::get_ship_name(const ship_info &info)
{
    std::string shipname = "";
    switch (info.ship_class)
    {
    case AIS_CLASS_A:
    case AIS_CLASS_B:
        shipname = info.shipname;
        break;
    case AIS_ATON:
        shipname = info.aton_name;
        break;
    case AIS_BASE:
        shipname = "";
        break;
    }

    return shipname;
}

void ais_info_model::remove_all()
{
    if (rowCount() > 0)
    {
        removeRows(0, rowCount());
    }

    sln_ship_info_manager::instance().clear();
}

QModelIndex ais_info_model::get_index(int mmsi)
{
    int row = find_item_row(mmsi);

    if (row < 0)
    {
        return QModelIndex();
    }
    else
    {
        return index(row, 0);
    }
}

void ais_info_model::update_data()
{
    sln_ship_info_manager::instance().travel_all_changed_target(
        boost::bind(&ais_info_model::update_ais_info, this, _1));

    sln_ship_info_manager::instance().travel_all_delete_keys(
        boost::bind(&ais_info_model::delete_ais_info, this, _1));
}

bool ais_info_model::delete_ais_info(const info_keys & key)
{
    int row = find_item_row(key.to_int());

    if (row >= 0)
    {
        removeRow(row);
    }

    return true;
}

Qt::ItemFlags ais_info_model::flags(const QModelIndex & index) const
{
    Qt::ItemFlags  flag = QStandardItemModel::flags(index);

    if (index.column() == AIS_MMSI_INDEX)
    {
        return (flag | Qt::ItemIsUserCheckable);
    }

    return flag;
}

bool ais_info_model::setData(const QModelIndex & index, const QVariant & value, int role)
{
    return QStandardItemModel::setData(index, value, role);
}